/*
 * @Author: xiaosihan 
 * @Date: 2023-03-17 21:29:45 
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2023-03-18 21:56:09
 */

import { BufferGeometry, Group, Mesh, MeshBasicMaterial, PlaneGeometry, DoubleSide, LinearEncoding } from "three";
import { degToRad } from "three/src/math/MathUtils";
import { PlaneText, threeLoader, Transition } from "three-base";
import JPG1 from "./1.jpg";
import JPG2 from "./2.jpg";
import JPG3 from "./3.jpg";
import JPG4 from "./4.jpg";
import JPG5 from "./5.jpg";
import JPG6 from "./6.jpg";
import utils from "@utils";
import { clamp } from "lodash";
import { Reflector } from "three/examples/jsm/objects/Reflector";
import Inverted from "./Inverted";



// 立方体对象
export default class Carousel extends Group {

    constructor() {
        super();
    }

    planeGeometry = (() => {
        const planeGeometry = new PlaneGeometry(7.05, 10, 1, 1);
        planeGeometry.translate(0, 5, 0);
        return planeGeometry;
    })();

    // 地板文字
    planeText = (() => {
        const planeText = new PlaneText("HelloTotem");
        planeText.scale.multiplyScalar(0.3);
        planeText.rotateX(degToRad(-90));
        planeText.position.set(0, 0.01, 0);
        this.add(planeText);
        return planeText;
    })();

    setText(text = "HelloTotem", color = "#ffffff") {
        this.planeText.set({ text, color });
        this.planeText.scale.multiplyScalar(0.3);
    }

    //第一个面
    plane1 = (() => {
        const plane1 = new Mesh<BufferGeometry, MeshBasicMaterial>(
            this.planeGeometry,
            new MeshBasicMaterial({ side: DoubleSide, map: threeLoader.getTexture(JPG1) })
        );
        this.add(plane1);
        return plane1;
    })();

    // 第一个面的倒影
    palne1Inverted = (() => {
        const palne1Inverted = new Inverted(this.planeGeometry);
        palne1Inverted.setMap(JPG1);
        this.add(palne1Inverted);
        return palne1Inverted;
    })();

    //第二个面
    plane2 = (() => {
        const plane2 = new Mesh<BufferGeometry, MeshBasicMaterial>(
            this.planeGeometry,
            new MeshBasicMaterial({ side: DoubleSide, map: threeLoader.getTexture(JPG2) })
        );
        this.add(plane2);
        return plane2;
    })();

    //第二个面的倒影
    palne2Inverted = (() => {
        const palne2Inverted = new Inverted(this.planeGeometry);
        palne2Inverted.setMap(JPG2);
        this.add(palne2Inverted);
        return palne2Inverted;
    })();

    //第三个面
    plane3 = (() => {
        const plane3 = new Mesh<BufferGeometry, MeshBasicMaterial>(
            this.planeGeometry,
            new MeshBasicMaterial({ side: DoubleSide, map: threeLoader.getTexture(JPG3) })
        );
        this.add(plane3);
        return plane3;
    })();

    //第三个面的倒影
    palne3Inverted = (() => {
        const palne3Inverted = new Inverted(this.planeGeometry);
        palne3Inverted.setMap(JPG3);
        this.add(palne3Inverted);
        return palne3Inverted;
    })();

    //第四个面
    plane4 = (() => {
        const plane4 = new Mesh<BufferGeometry, MeshBasicMaterial>(
            this.planeGeometry,
            new MeshBasicMaterial({ side: DoubleSide, map: threeLoader.getTexture(JPG4) })
        );
        this.add(plane4);
        return plane4;
    })();

    //第四个面的倒影
    palne4Inverted = (() => {
        const palne4Inverted = new Inverted(this.planeGeometry);
        palne4Inverted.setMap(JPG4);
        this.add(palne4Inverted);
        return palne4Inverted;
    })();

    //第五个面
    plane5 = (() => {
        const plane5 = new Mesh<BufferGeometry, MeshBasicMaterial>(
            this.planeGeometry,
            new MeshBasicMaterial({ side: DoubleSide, map: threeLoader.getTexture(JPG5) })
        );
        this.add(plane5);
        return plane5;
    })();

    //第五个面的倒影
    palne5Inverted = (() => {
        const palne5Inverted = new Inverted(this.planeGeometry);
        palne5Inverted.setMap(JPG5);
        this.add(palne5Inverted);
        return palne5Inverted;
    })();

    //第六个面
    plane6 = (() => {
        const plane6 = new Mesh<BufferGeometry, MeshBasicMaterial>(
            this.planeGeometry,
            new MeshBasicMaterial({ side: DoubleSide, map: threeLoader.getTexture(JPG6) })
        );
        this.add(plane6);
        return plane6;
    })();

    //第六个面的倒影
    palne6Inverted = (() => {
        const palne6Inverted = new Inverted(this.planeGeometry);
        palne6Inverted.setMap(JPG6);
        this.add(palne6Inverted);
        return palne6Inverted;
    })();

    //镜子
    // mirror = (() => {
    //     const plane = new PlaneGeometry(100, 100, 1, 1);
    //     const mirror = new Reflector(plane, {
    //         color: "#000",
    //         textureWidth: 2048,
    //         textureHeight: 2048,
    //         encoding: LinearEncoding
    //     });
    //     mirror.rotateX(degToRad(-90));
    //     this.add(mirror);
    //     return mirror;
    // })();

    timer = 0;

    // 初始循环动画
    initAnimation() {
        clearInterval(this.timer);
        this.transition.reset({ progress: 0 }).set({ progress: 1 });
        this.timer = setInterval(() => {
            this.transition.reset({ progress: 0 }).set({ progress: 1 });
        }, 15000);
    }

    // 特效变换对象
    transition = (() => {
        const transition = new Transition({ progress: 0 }).setDuration(2000).setBezier([0, 0, 1, 1]);
        transition.onChange(({ progress }) => {

            this.plane1.position.set((clamp(progress, 0, 0.5) * 2) * -15 * Math.sin(degToRad(360 - (300 * clamp(progress, 0, 0.5) * 2))), 0, (clamp(progress, 0, 0.5) * 2) * 15 * Math.cos(degToRad(360 - (300 * clamp(progress, 0, 0.5) * 2))));
            this.plane1.rotation.y = degToRad(300 * (clamp(progress, 0, 0.5) * 2));

            this.palne1Inverted.position.set((clamp(progress, 0, 0.5) * 2) * -15 * Math.sin(degToRad(360 - (300 * clamp(progress, 0, 0.5) * 2))), -0.2, (clamp(progress, 0, 0.5) * 2) * 15 * Math.cos(degToRad(360 - (300 * clamp(progress, 0, 0.5) * 2))));
            this.palne1Inverted.rotation.y = degToRad(300 * (clamp(progress, 0, 0.5) * 2));

            this.plane2.position.set(((clamp(progress, 0.1, 0.6) - 0.1) * 2) * -15 * Math.sin(degToRad(360 - (240 * (clamp(progress, 0.1, 0.6) - 0.1) * 2))), 0, ((clamp(progress, 0.1, 0.6) - 0.1) * 2) * 15 * Math.cos(degToRad(360 - (240 * (clamp(progress, 0.1, 0.6) - 0.1) * 2))));
            this.plane2.rotation.y = degToRad(240 * ((clamp(progress, 0.1, 0.6) - 0.1) * 2));

            this.palne2Inverted.position.set(((clamp(progress, 0.1, 0.6) - 0.1) * 2) * -15 * Math.sin(degToRad(360 - (240 * (clamp(progress, 0.1, 0.6) - 0.1) * 2))), -0.2, ((clamp(progress, 0.1, 0.6) - 0.1) * 2) * 15 * Math.cos(degToRad(360 - (240 * (clamp(progress, 0.1, 0.6) - 0.1) * 2))));
            this.palne2Inverted.rotation.y = degToRad(240 * ((clamp(progress, 0.1, 0.6) - 0.1) * 2));

            this.plane3.position.set(((clamp(progress, 0.2, 0.7) - 0.2) * 2) * -15 * Math.sin(degToRad(360 - (180 * (clamp(progress, 0.2, 0.7) - 0.2) * 2))), 0, ((clamp(progress, 0.2, 0.7) - 0.2) * 2) * 15 * Math.cos(degToRad(360 - (180 * (clamp(progress, 0.2, 0.7) - 0.2) * 2))));
            this.plane3.rotation.y = degToRad(180 * ((clamp(progress, 0.2, 0.7) - 0.2) * 2));

            this.palne3Inverted.position.set(((clamp(progress, 0.2, 0.7) - 0.2) * 2) * -15 * Math.sin(degToRad(360 - (180 * (clamp(progress, 0.2, 0.7) - 0.2) * 2))), -0.2, ((clamp(progress, 0.2, 0.7) - 0.2) * 2) * 15 * Math.cos(degToRad(360 - (180 * (clamp(progress, 0.2, 0.7) - 0.2) * 2))));
            this.palne3Inverted.rotation.y = degToRad(180 * ((clamp(progress, 0.2, 0.7) - 0.2) * 2));

            this.plane4.position.set(((clamp(progress, 0.3, 0.8) - 0.3) * 2) * -15 * Math.sin(degToRad(360 - (120 * (clamp(progress, 0.3, 0.8) - 0.3) * 2))), 0, ((clamp(progress, 0.3, 0.8) - 0.3) * 2) * 15 * Math.cos(degToRad(360 - (120 * (clamp(progress, 0.3, 0.8) - 0.3) * 2))));
            this.plane4.rotation.y = degToRad(120 * ((clamp(progress, 0.3, 0.8) - 0.3) * 2));

            this.palne4Inverted.position.set(((clamp(progress, 0.3, 0.8) - 0.3) * 2) * -15 * Math.sin(degToRad(360 - (120 * (clamp(progress, 0.3, 0.8) - 0.3) * 2))), -0.2, ((clamp(progress, 0.3, 0.8) - 0.3) * 2) * 15 * Math.cos(degToRad(360 - (120 * (clamp(progress, 0.3, 0.8) - 0.3) * 2))));
            this.palne4Inverted.rotation.y = degToRad(120 * ((clamp(progress, 0.3, 0.8) - 0.3) * 2));

            this.plane5.position.set(((clamp(progress, 0.4, 0.9) - 0.4) * 2) * -15 * Math.sin(degToRad(360 - (60 * (clamp(progress, 0.4, 0.9) - 0.4) * 2))), 0, ((clamp(progress, 0.4, 0.9) - 0.4) * 2) * 15 * Math.cos(degToRad(360 - (60 * (clamp(progress, 0.4, 0.9) - 0.4) * 2))));
            this.plane5.rotation.y = degToRad(60 * ((clamp(progress, 0.4, 0.9) - 0.4) * 2));

            this.palne5Inverted.position.set(((clamp(progress, 0.4, 0.9) - 0.4) * 2) * -15 * Math.sin(degToRad(360 - (60 * (clamp(progress, 0.4, 0.9) - 0.4) * 2))), -0.2, ((clamp(progress, 0.4, 0.9) - 0.4) * 2) * 15 * Math.cos(degToRad(360 - (60 * (clamp(progress, 0.4, 0.9) - 0.4) * 2))));
            this.palne5Inverted.rotation.y = degToRad(60 * ((clamp(progress, 0.4, 0.9) - 0.4) * 2));

            this.plane6.position.set(((clamp(progress, 0.5, 1.0) - 0.5) * 2) * -15 * Math.sin(degToRad(360 - (0 * (clamp(progress, 0.5, 1.0) - 0.5) * 2))), 0, ((clamp(progress, 0.5, 1.0) - 0.5) * 2) * 15 * Math.cos(degToRad(360 - (0 * (clamp(progress, 0.5, 1.0) - 0.5) * 2))));
            this.plane6.rotation.y = degToRad(0 * ((clamp(progress, 0.5, 1.0) - 0.5) * 2));

            this.palne6Inverted.position.set(((clamp(progress, 0.5, 1.0) - 0.5) * 2) * -15 * Math.sin(degToRad(360 - (0 * (clamp(progress, 0.5, 1.0) - 0.5) * 2))), 0, ((clamp(progress, 0.5, 1.0) - 0.5) * 2) * 15 * Math.cos(degToRad(360 - (0 * (clamp(progress, 0.5, 1.0) - 0.5) * 2))));
            this.palne6Inverted.rotation.y = degToRad(0 * ((clamp(progress, 0.5, 1.0) - 0.5) * 2));

        });
        return transition;
    })();

    // 换图
    async changeMap(index: 0 | 1 | 2 | 3 | 4 | 5) {
        const blob = await utils.selectFileToBlob();
        if (blob) {
            [this.plane1, this.plane2, this.plane3, this.plane4, this.plane5, this.plane6][index].material.map = threeLoader.getTexture(blob);
            [this.palne1Inverted, this.palne2Inverted, this.palne3Inverted, this.palne4Inverted, this.palne5Inverted, this.palne6Inverted][index].setMap(blob);
        }
        return blob || "";
    }


}


